package com.ruicar.afs.cloud.afscase.common.step;

import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author Peng_Jinbo
 * @Date 2020/06/23 12:18
 */
@Builder
@Data
@Slf4j
public class Steps {
    public static final Integer ERR_STEP = 101;
    public static final Integer END_STEP = 100;
    private Map<Integer, StepInvoker> orderSteps;
    private Integer maxStep;
    private Integer currentStep;

    public Steps then(StepInvoker stepInvoker) {
        orderSteps.put(orderSteps.size() - 2, stepInvoker);
        this.maxStep = orderSteps.size() - 2;
        return this;
    }

    public Steps err(StepInvoker stepInvoker) {
        orderSteps.put(ERR_STEP, stepInvoker);
        return this;
    }

    public Steps end(StepInvoker stepInvoker) {
        orderSteps.put(END_STEP, stepInvoker);
        return this;
    }

    public void doStep(StepParam param) {
        try {
            if (!currentStep.equals(END_STEP) && !currentStep.equals(ERR_STEP)) {
                if (currentStep < maxStep) {
                    param.setStillAddStep(false);
                    if (orderSteps.get(currentStep).invoke(param, currentStep)) {
                        currentStep++;
                        doStep(param);
                    } else {
                        orderSteps.get(ERR_STEP).invoke(param, param.isStillAddStep() ? currentStep + 1 : currentStep);
                    }
                } else {
                    orderSteps.get(END_STEP).invoke(param, END_STEP);
                }
            }
        } catch (Exception e) {
            try {
                log.error("步骤执行失败，执行异常处理",e);
                orderSteps.get(ERR_STEP).invoke(param, currentStep);
            } catch (Exception ex) {
                log.error("步骤异常处理失败",e);
            }
        }
    }

    public void doStep(StepParam param, Integer index) {
        currentStep = index;
        if (orderSteps.containsKey(index)) {
            doStep(param);
        }
    }

    public static Steps create() {
        return Steps.builder().currentStep(0).orderSteps(new HashMap<>()).build().err((stepParam, currentStep) -> true).end((stepParam, currentStep) -> true);
    }
}
